package com.cxx.admin.util;

import com.cxx.admin.dto.FtpInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.PrintCommandListener;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;

import java.io.*;
import java.nio.charset.StandardCharsets;

/**
 * @Author: Cxx
 * @Date: 2024/9/24 21:49
 * @Description:
 */
@Slf4j
public class FtpUtils {
    private static FTPClient ftpClient;

    /**
     * 文件名分隔符
     */
    public static String FILE_NAME_SPLIT = "_";

    private static boolean connectFtp(FtpInfo ftpInfo) {
        try {
            ftpClient = new FTPClient();
            // 设置utf-8 编码 否则中文文件名会乱码
            ftpClient.setControlEncoding("utf-8");
            ftpClient.connect(ftpInfo.getFtpIp(), ftpInfo.getFtpPort());
            ftpClient.login(ftpInfo.getFtpUsername(), ftpInfo.getFtpPassword());
            ftpClient.addProtocolCommandListener(
                    new PrintCommandListener(
                            new PrintWriter(new OutputStreamWriter(System.out, StandardCharsets.UTF_8)), true));
            log.info("连接ftp服务器成功");
        } catch (IOException e) {
            log.error("连接ftp服务器失败：", e);
            throw new RuntimeException("连接ftp服务器失败");
        }

        return true;
    }

    private static void disConnectFtp() {
        try {
            if (ftpClient != null) {
                ftpClient.disconnect();
            }
            log.info("关闭ftp服务器成功");
        } catch (IOException e) {
            log.error("关闭ftp服务器失败：", e);
            throw new RuntimeException("关闭ftp服务器失败");
        }
    }

    private static void closeInputStream(FileInputStream fileInputStream) {
        try {
            if (fileInputStream != null) {
                fileInputStream.close();
            }
        } catch (IOException e) {
            log.error("关闭文件流失败：", e);
            throw new RuntimeException("关闭文件流失败");
        }
    }

    public static void uploadFile(FtpInfo ftpInfo, String remotePath, String fileName, File file) {
        FileInputStream fileInputStream = null;

        try {
            if (connectFtp(ftpInfo)) {
                ftpClient.changeWorkingDirectory(remotePath);
                ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
                fileInputStream = new FileInputStream(file);
                boolean uploadResult = ftpClient.storeFile(fileName, fileInputStream);
                if (uploadResult) {
                    log.info("上传文件：{}成功", fileName);
                } else {
                    throw new RuntimeException("上传ftp文件失败");
                }
            }
        } catch (IOException e) {
            log.error("上传ftp文件异常：", e);
            throw new RuntimeException("上传ftp文件异常");
        } finally {
            disConnectFtp();
            closeInputStream(fileInputStream);
        }
    }

    /**
     * 校验是否存在文件
     *
     * @param ftpInfo    ftp信息
     * @param remotePath 文件路径
     * @param md5        md5值
     * @return 校验结果
     */
    public static boolean checkIsExitFile(FtpInfo ftpInfo, String remotePath, String md5) {
        boolean isExist = false;
        try {
            if (connectFtp(ftpInfo)) {
                ftpClient.changeWorkingDirectory(remotePath);
                FTPFile[] fileList = ftpClient.listFiles();
                if (fileList != null) {
                    for (FTPFile imageFile : fileList) {
                        String fileMd5 = imageFile.getName().split(FILE_NAME_SPLIT)[0];
                        if (fileMd5.equals(md5)) {
                            log.info("文件{}已经存在", imageFile.getName());
                            isExist = true;
                        }
                    }
                }
            }
        } catch (IOException e) {
            log.error("校验ftp文件异常：", e);
            throw new RuntimeException("校验ftp文件异常");
        } finally {
            disConnectFtp();
        }

        return isExist;
    }
}
